package com.zhiche.wms.configuration;

import org.aspectj.lang.annotation.Aspect;
import org.assertj.core.util.Lists;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.*;

import java.util.ArrayList;

/**
 * <p>
 * 平台事务增强
 * </p>
 *
 * @author user
 */
@Aspect
@Configuration
public class TransactionalConfigForBoot {

    private static final String AOP_POINTCUT_EXPRESSION = "execution(* com.***.service..*.*(..))";

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Bean
    public TransactionInterceptor txAdvice() {

        RuleBasedTransactionAttribute txAttr_REQUIRED = new RuleBasedTransactionAttribute();
        txAttr_REQUIRED.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        ArrayList<RollbackRuleAttribute> list = Lists.newArrayList();
        RollbackRuleAttribute rule = new RollbackRuleAttribute(Exception.class);
        list.add(rule);
        txAttr_REQUIRED.setRollbackRules(list);

        DefaultTransactionAttribute txAttr_REQUIRED_READONLY = new DefaultTransactionAttribute();
        txAttr_REQUIRED_READONLY.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        txAttr_REQUIRED_READONLY.setReadOnly(true);

        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

        source.addTransactionalMethod("save*", txAttr_REQUIRED);
        source.addTransactionalMethod("add*", txAttr_REQUIRED);
        source.addTransactionalMethod("create*", txAttr_REQUIRED);
        source.addTransactionalMethod("update*", txAttr_REQUIRED);
        source.addTransactionalMethod("cancel*", txAttr_REQUIRED);
        source.addTransactionalMethod("delete*", txAttr_REQUIRED);
        source.addTransactionalMethod("exec*", txAttr_REQUIRED);
        source.addTransactionalMethod("set*", txAttr_REQUIRED);
        source.addTransactionalMethod("get*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("query*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("list*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("count*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("is*", txAttr_REQUIRED_READONLY);

        return new TransactionInterceptor(transactionManager, source);
    }

    @Bean
    public Advisor txAdviceAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }

//    private DataSourceTransactionManager transactionManager;
//
//    @Autowired
//    public void setTransactionManager(DataSourceTransactionManager transactionManager) {
//        this.transactionManager = transactionManager;
//    }
//
//    // 创建事务通知
//    @Bean(name = "txAdvice")
//    @Primary
//    public TransactionInterceptor getAdvisor() {
//        Properties properties = new Properties();
//        properties.setProperty("get*", "PROPAGATION_NOT_SUPPORTED,-Exception,readOnly");
//        properties.setProperty("query*", "PROPAGATION_NOT_SUPPORTED,-Exception,readOnly");
//        properties.setProperty("add*", "PROPAGATION_REQUIRED,-Exception");
//        properties.setProperty("put*", "PROPAGATION_REQUIRED,-Exception");
//        properties.setProperty("save*", "PROPAGATION_REQUIRED,-Exception");
//        properties.setProperty("insert*", "PROPAGATION_REQUIRED,-Exception");
//        properties.setProperty("create*", "PROPAGATION_REQUIRED,-Exception");
//        properties.setProperty("update*", "PROPAGATION_REQUIRED,-Exception");
//        properties.setProperty("confirm*", "PROPAGATION_REQUIRED,-Exception");
//        properties.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception");
//        return new TransactionInterceptor(transactionManager, properties);
//    }
//
//    @Bean
//    public BeanNameAutoProxyCreator txProxy() {
//        BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator();
//        creator.setInterceptorNames("txAdvice");
//        creator.setBeanNames("*Service", "*ServiceImpl");
//        creator.setProxyTargetClass(true);
//        return creator;
//    }


}
